package com.ug_project.spring_dict.com.ug_project.spring_dict.DataAccess

import com.ug_project.spring_dict.DataAccess.Migrations.DictTables.*
import com.ug_project.spring_dict.DataAccess.connectDb
import com.ug_project.spring_dict.com.ug_project.spring_dict.Entities.SearchResult
import com.ug_project.spring_dict.com.ug_project.spring_dict.Entities.WordItem
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction

class SearchRepository {

    fun search(keyWord: String, from: String = "En-Ug", searchMode: String = "startsWith", pageIndex: Int = 0, count: Int = 50): SearchResult {
        var count = count
        if (count > 50) count = 50

        val condition = when (searchMode.toLowerCase()) {
            "startswith" -> "${keyWord}%"
            "contains" -> "%${keyWord}%"
            "endswith" -> "%${keyWord}"
            else -> keyWord.trim()
        }

        val table = getTableByKeyWordOrDirectionCode(code = from, word = keyWord)

        val words = transaction(connectDb()) {
            table.select {
                table.key like condition and (table.accessibility eq DictTable.Companion.Accessibility.Available)
            }.adjustSlice {
                slice(table.key, table.value, table.id)
            }.limit(count, pageIndex * count).map {
                it.toEntity(table)
            }
        }

        return SearchResult(words, getLangCodeByTable(table))
    }

    fun getWordById(langCode: String, wordId: Int) = transaction(connectDb()) {
        val table = getTableByLangCode(langCode)
        table.select { table.id eq wordId }.map { it.toEntity(table) }.singleOrNull()
    }

    fun ResultRow.toEntity(table: DictTable) = WordItem(
            this[table.key],
            this[table.value],
            this[table.id]
    )

    fun languageDetector(keyWord: String): Lang {
        val firstWordCode = keyWord.first()

        var code = Lang.Unknown

        if ("ئبپتجچخدرزژسشفقكگڭلمنھۋي".contains(firstWordCode)) {
            code = Lang.Ug
            return code
        }


        if (firstWordCode.toInt() in 65..90 || firstWordCode.toInt() in 97..122) {
            code = Lang.En
            return code
        }

        if (firstWordCode.toInt() in 19968..171941) {
            code = Lang.Zh
            return code
        }

        return code
    }

    fun getTableByKeyWordOrDirectionCode(word: String, code: String) : DictTable{
        val lang =languageDetector(word.toLowerCase())
        var table: DictTable = EnUg
        if (code == "auto-auto"){
            table = when (lang) {
                Lang.En -> EnUg
                Lang.Zh -> ZhUg
                Lang.Ug -> UgZh
                else -> UgZh
            }
        }
        else {
            table = when (code){
                "ug-zh", "zh-ug" -> if (lang == Lang.Zh) ZhUg else UgZh
                "ug-en", "en-ug" -> if (lang == Lang.En) EnUg else UgEn
                "ug-ug" -> UgZh
                else -> EnUg
            }
        }

        return table
    }

    fun getTableByLangCode(langCode: String) = when (langCode.toLowerCase()) {
        "zh-ug" -> ZhUg
        "ug-zh" -> UgZh
        "en-ug" -> EnUg
        "ug-en" -> UgEn
        else -> UgUg
    }

    fun getLangCodeByTable(table: DictTable) = when (table) {
        EnUg -> "en-ug"
        ZhUg -> "zh-ug"
        UgZh -> "ug-zh"
        UgEn -> "ug-en"
        UgUg -> "ug-ug"
        else -> "ug-zh"
    }
}

enum class Lang {
    En, Ug, Zh, Ar, Jp, Tr, Unknown
}